fix(desktop): badge relay-admitted agents as channel members - #6919
Open
arakakileo wants to merge 3 commits into
Open
fix(desktop): badge relay-admitted agents as channel members#6919arakakileo wants to merge 3 commits into
arakakileo wants to merge 3 commits into
Conversation
…n mention autocomplete An agent managed on another install that joins a channel appears in the relay's live agent directory with that channel in channelIds — the same relay-signed fact that admits it into autocomplete (relayAgentCanRespondInChannel) and authorizes mention delivery. But the relay-agent candidate loop in useMentions hardcoded isMember: false, and mentionSuggestionMapping derives the notInChannel badge from isMember === false, so while the member-roster cache was stale (up to CHANNEL_MEMBERS_STALE_TIME_MS = 5 min) an admitted, deliverable agent was badged "not in channel" in the very channel it had joined. Derive isMember for relay-agent candidates from the directory's channelIds in channel-scoped mention surfaces (stream/forum). Outside channel-scoped surfaces the badge keeps reflecting the roster only. Adds useMentionsRemoteMembership.test.mjs driving the real hook through a stale-roster repro: directory-confirmed member must not carry the badge, fresh-roster and managed-outside-channel cases pin the fix's scope. Signed-off-by: arakakileo <leooarakaki@gmail.com>
GATE 1 rework for the remote-agent membership badge fix.
The new useMentionsRemoteMembership suite passed in ~1s but its node --test
process only exited after ~302s without --test-force-exit. Instrumented
timer bookkeeping shows the survivors: twelve 300000ms GC timers from
@tanstack/query-core, scheduled by Query.removeObserver -> scheduleGc when
each test's last observer unmounts. cleanup() unmounts React but never
touches the QueryClient, so the GC timers keep the event loop alive for
the full 5 minutes.
Track the per-test QueryClients and clear() them in afterEach:
client.clear() removes all queries, and Removable.destroy() cancels the
pending GC timeout. Focal runner now exits 0 in ~8s with no force-exit.
The full-suite run then exposed a pre-existing flake in
useDocumentVisible.test.mjs ("focused polling pauses on blur and resumes
after activation yields"): the resume notification is delivered through
scheduleAfterForegroundReady's chained 0ms timers, and under full-suite
load those timers exceed the test's fixed 10ms real-time wait. Proven
base flake: ceb8ba6 reproduces the identical failure signature (1/4
runs, same AssertionError + post-teardown "window is not defined" from
the late trailing task). Make the wait deterministic by polling for the
resume with a 5s deadline instead of a constant sleep, and bail out if
the window global was already restored so a late resume cannot throw
into an unrelated test's output.
Full desktop suite without --test-force-exit: 3x consecutive runs exit 0
(5674/5674 each). biome, tsc --noEmit, and git diff --check green.
Signed-off-by: arakakileo <leooarakaki@gmail.com>
…ll IPC
GATE 1 rework round 2 for the remote-agent membership badge fix.
The Friday gate proved timers still active after client.clear() at
fe78a2b19: in-flight queries re-arm stale/GC timers. Root cause is an
ordering race in @tanstack/query-core 5.100.14: Query.fetch() ends with
`finally { this.scheduleGc() }`, so a fetch that settles AFTER clear()
re-arms a 300s GC timer on a query that clear() already removed from the
cache — nobody ever calls destroy() on it again, and the timer holds the
event loop open.
Fix, in afterEach, in order:
- await client.cancelQueries() first: settles every in-flight fetch
(the CancelledError path also runs the finally) while the queries are
still cache-resident, so scheduleGc() lands before removal;
- await client.clear() after: remove() -> destroy() -> clearGcTimeout()
now finds and cancels every GC timer.
The remaining ~5s post-assertion tail was a separate leak: mediaUrl.ts
starts a shared proxy-port poll at module load (it sees the JSDOM
window), and the fixture only installed IPC handlers after the
production imports, so the poll spun its full 5s deadline on rejected
invokes. Install static success handlers for get_relay_http_url and
get_media_proxy_port before any production import so the poll resolves
on its first iteration. Also close the JSDOM window in after() so the
dom itself cannot keep the loop referenced.
Evidence at this SHA:
- focal 3/3 exit 0, wall ~4.3s each (was ~8s), no force-exit;
timer-leak probe shows zero surviving timers >=100ms;
- full desktop suite 3x consecutive: 5674/5674 exit 0, wall 120-125s,
no force-exit;
- biome check and tsc --noEmit clean.
Signed-off-by: arakakileo <leooarakaki@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
channelIdscontains the active channel as channel members in mention autocomplete.Test plan
node --import ./test-loader.mjs --experimental-strip-types --test src/features/messages/lib/useMentionsRemoteMembership.test.mjs— 3/3pnpm test— 5675/5675pnpm typecheckpnpm exec biome checkon the three changed filesgit diff --check origin/main...HEADIntegration
block/buzz@b622003f7.bab1b08f31ebbb05ae558b5bfb62ad132c377ca4.7ac8715c-4f45-4c24-8f15-0f1e6289c854.Risk / rollback